home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / tcpuser.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  9KB  |  379 lines

  1. /* User calls to TCP
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "socket.h"
  10. #include "internet.h"
  11. #include "tcp.h"
  12. #include "ip.h"
  13. #include "icmp.h"
  14. #include "proc.h"
  15.  
  16. int16 Tcp_window = DEF_WND;
  17.  
  18. struct tcb *open_tcp(
  19.     struct socket *lsocket,            /* Local socket */
  20.     struct socket *fsocket,            /* Remote socket */
  21.     int mode,                            /* Active/passive/server */
  22.     int16 window,                        /* Receive window (and send buffer) sizes        */
  23.     void (*r_upcall)(struct tcb *tcb, int cnt),    /* upcall Fn -  data arrived     */
  24.     void (*t_upcall)(struct tcb *tcb, int cnt),    /* upcall Fn -  ok to send       */
  25.     void (*s_upcall)(struct tcb *tcb, int old, int new),    /* conn state change */
  26.     int tos,
  27.     int user )                            /* User linkage area */
  28. {
  29.     struct connection conn;
  30.     register struct tcb *tcb;
  31.  
  32.     if(lsocket == NULLSOCK){
  33.         Net_error = INVALID;
  34.         return NULLTCB;
  35.     }
  36.     conn.local.address = lsocket->address;
  37.     conn.local.port = lsocket->port;
  38.     if(fsocket != NULLSOCK){
  39.         conn.remote.address = fsocket->address;
  40.         conn.remote.port = fsocket->port;
  41.     } else {
  42.         conn.remote.address = 0;
  43.         conn.remote.port = 0;
  44.     }
  45.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  46.         if((tcb = create_tcb(&conn)) == NULLTCB){
  47.             Net_error = NO_MEM;
  48.             return NULLTCB;
  49.         }
  50.     } else if(tcb->state != TCP_LISTEN){
  51.         Net_error = CON_EXISTS;
  52.         return NULLTCB;
  53.     }
  54.     tcb->user = user;
  55.     if(window != 0)
  56.         tcb->window = tcb->rcv.wnd = window;
  57.     else
  58.         tcb->window = tcb->rcv.wnd = Tcp_window;
  59.     tcb->snd.wnd = 1;    /* Allow space for sending a SYN */
  60.     tcb->r_upcall = r_upcall;
  61.     tcb->t_upcall = t_upcall;
  62.     tcb->s_upcall = s_upcall;
  63.     tcb->tos = tos;
  64.     switch(mode){
  65.     case TCP_SERVER:
  66.         tcb->flags.clone = 1;
  67.     case TCP_PASSIVE:    /* Note fall-thru */
  68.         setstate(tcb,TCP_LISTEN);
  69.         break;
  70.     case TCP_ACTIVE:
  71.         /* Send SYN, go into TCP_SYN_SENT state */
  72.         tcb->flags.active = 1;
  73.         send_syn(tcb);
  74.         setstate(tcb,TCP_SYN_SENT);
  75.         tcp_output(tcb);
  76.         break;
  77.     }
  78.     return tcb;
  79. }
  80. /* User send routine */
  81. int
  82. send_tcp(tcb,bp)
  83. register struct tcb *tcb;
  84. struct mbuf *bp;
  85. {
  86.     int16 cnt;
  87.  
  88.     if(tcb == NULLTCB || bp == NULLBUF){
  89.         free_p(bp);
  90.         Net_error = INVALID;
  91.         return -1;
  92.     }
  93.     cnt = len_p(bp);
  94.     switch(tcb->state){
  95.     case TCP_CLOSED:
  96.         free_p(bp);
  97.         Net_error = NO_CONN;
  98.         return -1;
  99.     case TCP_LISTEN:
  100.         if(tcb->conn.remote.address == 0 && tcb->conn.remote.port == 0){
  101.             /* Save data for later */
  102.             append(&tcb->sndq,bp);
  103.             tcb->sndcnt += cnt;
  104.             break;
  105.         }        
  106.         /* Change state from passive to active */
  107.         tcb->flags.active = 1;
  108.         send_syn(tcb);
  109.         setstate(tcb,TCP_SYN_SENT);    /* Note fall-thru */
  110.     case TCP_SYN_SENT:
  111.     case TCP_SYN_RECEIVED:
  112.     case TCP_ESTABLISHED:
  113.     case TCP_CLOSE_WAIT:
  114.         append(&tcb->sndq,bp);
  115.         tcb->sndcnt += cnt;
  116.         tcp_output(tcb);
  117.         break;
  118.     case TCP_FINWAIT1:
  119.     case TCP_FINWAIT2:
  120.     case TCP_CLOSING:
  121.     case TCP_LAST_ACK:
  122.     case TCP_TIME_WAIT:
  123.         free_p(bp);
  124.         Net_error = CON_CLOS;
  125.         return -1;
  126.     }
  127.     return (int)cnt;
  128. }
  129. /* User receive routine */
  130.  
  131. int recv_tcp(
  132.     struct tcb *tcb,
  133.     struct mbuf **bpp,
  134.     int16 cnt )
  135. {
  136.     if(tcb == NULLTCB || bpp == (struct mbuf **)NULL){
  137.         Net_error = INVALID;
  138.         return -1;
  139.     }
  140.     if(tcb->rcvcnt == 0){
  141.         /* If there's nothing on the queue, our action depends on what state
  142.          * we're in (i.e., whether or not we're expecting any more data).
  143.          * If no more data is expected, then simply return 0; this is
  144.          * interpreted as "end of file". Otherwise return -1.
  145.          */
  146.         switch(tcb->state){
  147.         case TCP_LISTEN:
  148.         case TCP_SYN_SENT:
  149.         case TCP_SYN_RECEIVED:
  150.         case TCP_ESTABLISHED:
  151.         case TCP_FINWAIT1:
  152.         case TCP_FINWAIT2:
  153.             Net_error = WOULDBLK;
  154.             return -1;
  155.         case TCP_CLOSED:
  156.         case TCP_CLOSE_WAIT:
  157.         case TCP_CLOSING:
  158.         case TCP_LAST_ACK:
  159.         case TCP_TIME_WAIT:
  160.             *bpp = NULLBUF;
  161.             return 0;
  162.         }
  163.     }
  164.     /* cnt == 0 means "I want it all" */
  165.     if(cnt == 0)
  166.         cnt = tcb->rcvcnt;
  167.     /* See if the user can take all of it */
  168.     if(tcb->rcvcnt <= cnt){
  169.         cnt = tcb->rcvcnt;
  170.         *bpp = tcb->rcvq;
  171.         tcb->rcvq = NULLBUF;
  172.     } else {
  173.         *bpp = ambufw(cnt);
  174.         pullup(&tcb->rcvq,(*bpp)->data,cnt);
  175.         (*bpp)->cnt = cnt;
  176.     }
  177.     tcb->rcvcnt -= cnt;
  178.     tcb->rcv.wnd += cnt;
  179.     /* Do a window update if it was closed */
  180.     if(cnt == tcb->rcv.wnd){
  181.         tcb->flags.force = 1;
  182.         tcp_output(tcb);
  183.     }
  184.     return (int)cnt;
  185. }
  186. /* This really means "I have no more data to send". It only closes the
  187.  * connection in one direction, and we can continue to receive data
  188.  * indefinitely.
  189.  */
  190. int
  191. close_tcp(tcb)
  192. register struct tcb *tcb;
  193. {
  194.     if(tcb == NULLTCB){
  195.         Net_error = INVALID;
  196.         return -1;
  197.     }
  198.     switch(tcb->state){
  199.     case TCP_CLOSED:
  200.         return 0;    /* Unlikely */
  201.     case TCP_LISTEN:
  202.     case TCP_SYN_SENT:
  203.         close_self(tcb,NORMAL);
  204.         return 0;
  205.     case TCP_SYN_RECEIVED:
  206.     case TCP_ESTABLISHED:
  207.         tcb->sndcnt++;
  208.         tcb->snd.nxt++;
  209.         setstate(tcb,TCP_FINWAIT1);
  210.         tcp_output(tcb);
  211.         return 0;
  212.     case TCP_CLOSE_WAIT:
  213.         tcb->sndcnt++;
  214.         tcb->snd.nxt++;
  215.         setstate(tcb,TCP_LAST_ACK);
  216.         tcp_output(tcb);
  217.         return 0;
  218.     case TCP_FINWAIT1:
  219.     case TCP_FINWAIT2:
  220.     case TCP_CLOSING:
  221.     case TCP_LAST_ACK:
  222.     case TCP_TIME_WAIT:
  223.         Net_error = CON_CLOS;
  224.         return -1;
  225.     }
  226.     return -1;    /* "Can't happen" */
  227. }
  228. /* Delete TCB, free resources. The user is not notified, even if the TCB is
  229.  * not in the TCP_CLOSED state. This function should normally be called by the
  230.  * user only in response to a state change upcall to TCP_CLOSED state.
  231.  */
  232. int
  233. del_tcp(conn)
  234. struct tcb *conn;
  235. {
  236.     register struct tcb *tcb;
  237.     struct tcb *tcblast = NULLTCB;
  238.     struct reseq *rp,*rp1;
  239.  
  240.     /* Remove from list */
  241.     for(tcb=Tcbs;tcb != NULLTCB;tcblast = tcb,tcb = tcb->next)
  242.         if(tcb == conn)
  243.             break;
  244.     if(tcb == NULLTCB){
  245.         Net_error = INVALID;
  246.         return -1;    /* conn was NULL, or not on list */ 
  247.     }
  248.     if(tcblast != NULLTCB)
  249.         tcblast->next = tcb->next;
  250.     else
  251.         Tcbs = tcb->next;    /* was first on list */
  252.  
  253.     stop_timer(&tcb->timer);
  254.     for(rp = tcb->reseq;rp != NULLRESEQ;rp = rp1){
  255.         rp1 = rp->next;
  256.         free_p(rp->bp);
  257.         free((char *)rp);
  258.     }
  259.     tcb->reseq = NULLRESEQ;
  260.     free_p(tcb->rcvq);
  261.     free_p(tcb->sndq);
  262.     free((char *)tcb);
  263.     return 0;
  264. }
  265. /* Return 1 if arg is a valid TCB, 0 otherwise */
  266. int
  267. tcpval(tcb)
  268. struct tcb *tcb;
  269. {
  270.     register struct tcb *tcb1;
  271.  
  272.     if(tcb == NULLTCB)
  273.         return 0;    /* Null pointer can't be valid */
  274.     for(tcb1=Tcbs;tcb1 != NULLTCB;tcb1 = tcb1->next){
  275.         if(tcb1 == tcb)
  276.             return 1;
  277.     }
  278.     return 0;
  279. }
  280. /* Kick a particular TCP connection */
  281. int
  282. kick_tcp(tcb)
  283. register struct tcb *tcb;
  284. {
  285.     if(!tcpval(tcb))
  286.         return -1;
  287.     tcb->flags.force = 1;    /* Send ACK even if no data */
  288.     tcp_timeout(tcb);
  289.     return 0;
  290. }
  291. /* Kick all TCP connections to specified address; return number kicked */
  292. int
  293. kick(addr)
  294. int32 addr;
  295. {
  296.     register struct tcb *tcb;
  297.     int cnt = 0;
  298.  
  299.     for(tcb=Tcbs;tcb != NULLTCB;tcb = tcb->next){
  300.         if(tcb->conn.remote.address == addr){
  301.             kick_tcp(tcb);
  302.             cnt++;
  303.         }
  304.     }
  305.     return cnt;
  306. }
  307. /* Clear all TCP connections */
  308. void
  309. reset_all()
  310. {
  311.     register struct tcb *tcb;
  312.  
  313.     for(tcb=Tcbs;tcb != NULLTCB;tcb = tcb->next)
  314.         reset_tcp(tcb);
  315.  
  316.     pwait(NULL);    /* Let the RSTs go forth */
  317. }
  318. void
  319. reset_tcp(tcb)
  320. register struct tcb *tcb;
  321. {
  322.     struct tcp fakeseg;
  323.     struct ip fakeip;
  324.  
  325.     if(tcb == NULLTCB)
  326.         return;
  327.     if(tcb->state != TCP_LISTEN){
  328.         /* Compose a fake segment with just enough info to generate the
  329.          * correct RST reply
  330.          */
  331.         memset((char *)&fakeseg,0,sizeof(fakeseg));
  332.         memset((char *)&fakeip,0,sizeof(fakeip));
  333.         fakeseg.dest = tcb->conn.local.port;
  334.         fakeseg.source = tcb->conn.remote.port;
  335.         fakeseg.flags.ack = 1;
  336.         /* Here we try to pick a sequence number with the greatest likelihood
  337.          * of being in his receive window.
  338.          */
  339.         fakeseg.ack = tcb->snd.nxt + tcb->snd.wnd - 1;
  340.         fakeip.dest = tcb->conn.local.address;
  341.         fakeip.source = tcb->conn.remote.address;
  342.         fakeip.tos = tcb->tos;
  343.         reset(&fakeip,&fakeseg);
  344.     }
  345.     close_self(tcb,RESET);
  346. }
  347. #ifdef    notused
  348. /* Return character string corresponding to a TCP well-known port, or
  349.  * the decimal number if unknown.
  350.  */
  351. char *
  352. tcp_port(n)
  353. int16 n;
  354. {
  355.     static char buf[32];
  356.  
  357.     switch(n){
  358.     case IPPORT_ECHO:
  359.         return "echo";
  360.     case IPPORT_DISCARD:
  361.         return "discard";
  362.     case IPPORT_FTPD:
  363.         return "ftp_data";
  364.     case IPPORT_FTP:
  365.         return "ftp";    
  366.     case IPPORT_TELNET:
  367.         return "telnet";
  368.     case IPPORT_SMTP:
  369.         return "smtp";
  370.     case IPPORT_POP:
  371.         return "pop";
  372.     default:
  373.         sprintf(buf,"%u",n);
  374.         return buf;
  375.     }
  376. }
  377. #endif
  378.  
  379.